﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;

namespace SW2A311_Lib
{
    /// <summary>
    /// Projekt-strukturen, der laver projekt elementer.
    /// </summary>
    [Serializable()]  // Objektet sættes til at være serialisérbart.
    public class ProjectData : ISerializable
    {
        #region Instansvariabler
        private DateTime _ProjectEnd;
        public DateTime ProjectEnd
        {
            get { return _ProjectEnd; }
            set
            {
                if (value >= ProjectStart)
                    _ProjectEnd = value;
                else
                    throw new ArgumentOutOfRangeException("Must be nonzero and equal to or after: " + ProjectStart.ToShortDateString());
            }
        }

        private DateTime _ProjectStart;
        public DateTime ProjectStart
        {
            get { return _ProjectStart; }
            set
            {
                if (value != DateTime.MinValue)
                    _ProjectStart = value;
                else
                    throw new ArgumentOutOfRangeException("Must be nonzero");
            }

        }

        public string ProjectName { get; set; }
        public string AssignedAdmin { get; set; }
        public List<Task> TaskList = new List<Task>();
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor der initialiserer et minimum af fields.
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="adminNameIn"></param>
        public ProjectData(string projectName, string adminNameIn)
        {
            this.AssignedAdmin = adminNameIn;
            this.ProjectName = projectName;
        }
        /// <summary>
        /// Standard constructoren til ProjectData objekter.
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="projectStart"></param>
        /// <param name="projectEnd"></param>
        /// <param name="adminNameIn"></param>
        public ProjectData(string projectName, DateTime projectStart, DateTime projectEnd, string adminNameIn)
        {
            this.AssignedAdmin = adminNameIn;
            this.ProjectName = projectName;
            this.ProjectStart = projectStart;
            this.ProjectEnd = projectEnd;
        }
        #endregion

        #region Metoder
        /// <summary>
        /// Constructer til når objektet skal serialiseres.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public ProjectData(SerializationInfo info, StreamingContext ctxt)
        {
            //Det er kun de properties der nævnes her der bliver serialiseret.
            this.ProjectEnd = (DateTime)info.GetValue("ProjectEnd", typeof(DateTime));
            this.ProjectStart = (DateTime)info.GetValue("ProjectStart", typeof(DateTime));
            this.ProjectName = (String)info.GetValue("ProjectName", typeof(String));
            this.AssignedAdmin = (string)info.GetValue("AssignedAdmin", typeof(string));
            this.TaskList = (List<Task>)info.GetValue("TaskList", typeof(List<Task>));
        }
        /// <summary>
        /// Metode der bruges til at deserialisere objektet.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public virtual void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            /* Skal indeholde de samme attributes som serialiserings-Constructeren, 
             * og de enkelte strings skal matche dem fra constructeren.
             * */
            info.AddValue("ProjectEnd", this.ProjectEnd);
            info.AddValue("ProjectStart", this.ProjectStart);
            info.AddValue("ProjectName", this.ProjectName);
            info.AddValue("AssignedAdmin", this.AssignedAdmin);
            info.AddValue("TaskList", this.TaskList);
        }
        /// <summary>
        /// Add Task metode der tager et Task objekt som input.
        /// </summary>
        /// <remarks>
        /// Hvis en 'ældre' version eksisterer overskrives den.
        /// Ellers tilføjes den TaskList'en.
        /// </remarks>
        /// <param name="task"></param>
        public void AddTask(Task task)
        {
            bool exists = false;

            for (int i = 0; i < TaskList.Count; i++)
            {
                if (task.TaskName == TaskList[i].TaskName)
                {
                    TaskList[i] = task;
                    exists = true;
                }
            }

            if (!exists)
            {
                TaskList.Add(task);
            }
        }
        /// <summary>
        /// Add Task metode der tager data som input.
        /// </summary>
        /// <remarks>
        /// Har check om task allerede eksisterer.
        /// </remarks>
        /// <param name="taskEnd"></param>
        /// <param name="taskStart"></param>
        /// <param name="taskName"></param>
        /// <param name="taskDescription"></param>
        public void AddTask(DateTime taskEnd, DateTime taskStart, string taskName, string taskDescription)
        {
            if (TaskList.Exists(x => x.TaskName == taskName))
            {
                throw new ArgumentException("Task name does already exist!");
            }
            else
            {
                Task NewTask = new Task(taskStart, taskEnd, taskName, taskDescription);
                TaskList.Add(NewTask);
            }
        }
        /// <summary>
        /// Fjerner project hvis det eksisterer og RemoveAll returnerer antal elementer fjernet.
        /// </summary>
        /// <param name="taskToDelete"></param>
        public void DeleteTask(string taskToDelete)
        {
            if (TaskList.RemoveAll(x => x.TaskName == taskToDelete) == 0)
            {
                throw new ArgumentOutOfRangeException("Task does not exist!");
            }
        }
        /// <summary>
        /// Laver en ObservableCollection med indholdet fra TaskList og returnerer den.
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<Task> GetObservableTasks()
        {
            return new ObservableCollection<Task>(TaskList);
        }
        /// <summary>
        /// Override af ToString metoden.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string taskString = "No tasks added.";
            if (TaskList.Count > 0)
            {
                taskString = string.Join("\n", TaskList);
            }

            return string.Format("Project Name: {0} Project Start: {1} Project End: {2} \n Task List: \n{3} \n Admin: \n{4}", ProjectName, ProjectStart, ProjectEnd,
                taskString, AssignedAdmin);
        }
        #endregion
    }
}
